import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:hi_barrage/barrage_item.dart';
import 'package:hi_barrage/barrage_model.dart';
import 'package:hi_barrage/barrage_view_util.dart';
import 'package:hi_barrage/hisocket.dart';
import 'package:hi_barrage/ibarrage.dart';

enum BarrageStatus {
  play,
  pause,
}

// 弹幕播放组件
class HBarrage extends StatefulWidget {
  final int lineCount; //行数
  final String vid; //id
  final int speed; //速度
  final double top; //距离顶部
  final bool autoPlay; //是否播放
  final Map<String, dynamic> headers;
  HBarrage({
    Key key,
    this.lineCount = 4,
    @required this.vid,
    this.speed = 800,
    this.top = 0,
    this.autoPlay = false,
    @required this.headers,
  }) : super(key: key);

  @override
  HBarrageState createState() => HBarrageState();
}

class HBarrageState extends State<HBarrage> implements IBarrage {
  // 变量
  HiSocket _hiSocket;
  double _height;
  double _width;
  List<BarrageItem> _barrageItemList = []; //弹幕widget集合 ；
  List<BarrageModel> _barrageModeList = []; //弹幕数据模型集合；
  int _barrageIndex = 0; //第几个弹幕
  Random _random = Random(); //随机数
  BarrageStatus _barrageStatus; //弹幕状态
  Timer _timer; //

  @override
  void initState() {
    super.initState();
    _hiSocket = HiSocket(widget.headers);
    _hiSocket.open(widget.vid).listen((value) {
      _handleMessage(value);
    });
  }

  @override
  void dispose() {
    if (_hiSocket != null) {
      _hiSocket.close();
    }
    if (_timer != null) {
      _timer.cancel();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    _width = MediaQuery.of(context).size.width;
    _height = _width / 16 * 9;
    return SizedBox(
      width: _width,
      height: _height,
      child: Stack(
        children: [
          // 防止Stack为空
          Container()
        ]..addAll(_barrageItemList),
      ),
    );
  }

// 处理消息 ，instant=true 立即发送
  void _handleMessage(List<BarrageModel> modelList, {bool instant = false}) {
    if (instant) {
      _barrageModeList.insertAll(0, modelList); //插入到最前面优先执行 ；
    } else {
      _barrageModeList.addAll(modelList);
    }
    // 收到新的弹幕后播放 ---状态判断
    if (_barrageStatus == BarrageStatus.play) {
      play();
      return;
    }
    if (widget.autoPlay && _barrageStatus != BarrageStatus.pause) {
      play();
    }
  }

  void play() {
    _barrageStatus = BarrageStatus.play;
    if (_timer != null && _timer.isActive) return;
    // hyLog('action:play', StackTrace.current);
    _timer = Timer.periodic(Duration(microseconds: widget.speed), (timer) {
      if (_barrageModeList.isNotEmpty) {
        // 将发送的弹幕将集合·中剔除
        var temp = _barrageModeList.removeAt(0);
        // 将弹幕放到屏幕上面去
        addBarrage(temp);
      } else {
        _timer.cancel();
        // hyLog('弹幕发送完毕', StackTrace.current);
      }
    });
  }

  void addBarrage(BarrageModel model) {
    // hyLog(temp.content, StackTrace.current);
    // 弹幕ui
    double perRowHeight = 30;
    // 当前还是第几行
    var line = _barrageIndex % widget.lineCount;
    _barrageIndex++;
    //
    var top = line * perRowHeight + widget.top;
    // 生成唯一id为每一条
    String id = '${_random.nextInt(10000)}:${model.content}';
    var item = BarrageItem(
      id: id,
      top: top,
      child: BarrageViewUtil.barrageView(model),
      onComplete: _onComplete,
    );
    _barrageItemList.add(item);
    // 刷新界面
    setState(() {});
  }

  @override
  void pause() {
    // 改状态
    _barrageStatus = BarrageStatus.pause;
    // 清空弹幕
    _barrageItemList.clear();
    setState(() {});
    _timer.cancel();
    // hyLog('action:pause', StackTrace.current);
  }

  @override
  void send(String message) {
    if (message == null) return;
    _hiSocket.send(message);
    _handleMessage(
        [BarrageModel(content: message, vid: '-1', priority: 1, type: 1)]);
  }

  void _onComplete(id) {
    // print('Dome:$id');
    // 弹幕播放完毕将其从弹幕widget集合中删除；
    _barrageItemList.removeWhere((element) => element.id == id);
  }
}
